/**
 *  @author Ion Morozan
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
package com.dddforandroid.database.local;

import java.lang.reflect.Type;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;

import org.apache.http.impl.client.DefaultHttpClient;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Toast;

import com.dddforandroid.database.server.NotePad;
import com.dddforandroid.database.server.NotePad.Notes;
import com.dddforandroid.database.server.SyncServerDatabase;
import com.dddforandroid.design.AddTaskActivity;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;


public class CreateNote extends AsyncTask<Void, Void, String> {

	/* The EditTexts for name, note and date */
	private final EditText nameET, noteET;

	private final DatePicker datePk;
	/* The Context of the application */
	Context mainActivity;
	/* The ServerDatabase object, used for synchronizing the server database */
	private SyncServerDatabase nosql;

	public DefaultHttpClient authClient = new DefaultHttpClient();

	/**
	 * Constructor used for the CreateNote class
	 * 
	 * @param nameET
	 *            Name EditText
	 * @param noteET
	 *            Note EditText
	 * @param dateET
	 *            Date EditText
	 * @param mainActivity
	 *            The Context of the application
	 * @param nosql
	 *            The ServerDatabase object
	 */
	public CreateNote(EditText nameET, EditText noteET, DatePicker datePk,
			Context mainActivity, SyncServerDatabase nosql,
			DefaultHttpClient http_client) {
		this.nameET = nameET;
		this.noteET = noteET;
		this.datePk = datePk;
		this.mainActivity = mainActivity;
		this.nosql = nosql;
		this.authClient = http_client;
	}

	/**
	 * What the new thread is supposed to do in background - create a new note
	 * and add it to the database
	 */
	@Override
	protected String doInBackground(Void... params) {
		/* Create random IDs for the objects in the database */
		UUID randomID = UUID.randomUUID();

		ContentValues mValues = new ContentValues();

		mValues.put(NotePad.Notes._ID, randomID.toString());
		mValues.put(NotePad.Notes.TITLE, nameET.getText().toString());
		mValues.put(NotePad.Notes.NOTE, noteET.getText().toString());

		int year, month, day;
		day = datePk.getDayOfMonth();
		month = datePk.getMonth();
		year = datePk.getYear();
		
		Calendar cal = Calendar.getInstance(Locale.ENGLISH);
		cal.set(year, month, day);


		mValues.put(NotePad.Notes.CREATED_DATE, cal.getTimeInMillis());

		// TODO verify if the name and description are already existent
		ContentResolver resolver = mainActivity.getContentResolver();
		/* Insert in the database a new Note */
		resolver.insert(NotePad.Notes.CONTENT_URI, mValues);

		try {
			addServerDB();
		} catch (ParseException e) {
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * Invoked after the background computation finishes. The result of the
	 * background computation is passed to this step as a parameter.
	 */
	protected void onPostExecute(String result) {
		nameET.setText("");
		noteET.setText("");

		Calendar cal = Calendar.getInstance(Locale.ENGLISH);
		cal.setTime(new Date());

		datePk.updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
				cal.get(Calendar.DATE));

		Toast.makeText(mainActivity, "Note successfully created!",
				Toast.LENGTH_SHORT).show();

		AddTaskActivity.progress.dismiss();
	}

	/**
	 * Method used when an add is made in the local database to synchronize the
	 * server database
	 * 
	 * @return The response got from the server after calling HttpPost method
	 * @throws ParseException
	 */
	private String addServerDB() throws ParseException {

		ContentResolver provider = mainActivity.getContentResolver();

		ArrayList<Notes> notes = new ArrayList<Notes>();

		String[] projection = new String[] { Notes._ID, Notes.TITLE, Notes.NOTE,
				Notes.CREATED_DATE };
		Uri queryUri = Notes.CONTENT_URI;

		/* Create a query */
		Cursor mCur = provider.query(queryUri, projection, null, null, null);

		/* Use the Cursor to move through the objects */
		if (mCur.moveToFirst()) {
			do {
				Notes current = getCurrentNote(mCur);
				notes.add(current);
			} while (mCur.moveToNext());
		}

		mCur.close();

		GsonBuilder builder = new GsonBuilder();
		// Register an adapter to manage the date types as long values
		builder.registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
			public JsonElement serialize(Date date, Type arg1,
					JsonSerializationContext arg2) {

				return new JsonPrimitive(date.getTime());
			}
		});
		Gson gson = builder.create();

		/* Put the data in JSON format using GSON */
		Type collectionType = new TypeToken<ArrayList<Notes>>() {
		}.getType();
		String JSONequiv = gson.toJson(notes, collectionType);

		String jsonString = nosql.createString(JSONequiv);
		
		String postResponse = nosql.postData(jsonString, authClient);
		
		return postResponse; 
	}

	/**
	 * Method used to initialize a new Note object with the current Strings from
	 * the database
	 * 
	 * @param mCur
	 *            The cursor used to move through the query results
	 * @return The Note object newly initialized
	 * @throws ParseException
	 */
	private Notes getCurrentNote(Cursor mCur) throws ParseException {
		Notes note = new Notes();

		note.setId(mCur.getString(mCur.getColumnIndex(NotePad.Notes._ID)));
		note.setTitle(mCur.getString(mCur.getColumnIndex(NotePad.Notes.TITLE)));
		note.setNote(mCur.getString(mCur.getColumnIndex(NotePad.Notes.NOTE)));
		Long date_str = mCur.getLong(mCur.getColumnIndex(NotePad.Notes.CREATED_DATE));
		
		note.setCreatedDate(date_str);

		return note;
	}

}
